<?php
namespace app\common\utils\rsa;
/**
 * PHP RSA密文过长加密解密 越过1024的解决代码
 * 私钥加密 ==> 公钥解密
 * 公钥加密 ==> 私钥解密
 * 私钥加密 =/=> 私钥不能解密
 * 公钥加密 =/=> 公钥不能解密
 */
class Rsa1024 {
    /**
     * @Title: urlsafe_b64encode
     * @Description: todo(加密码时把特殊符号替换成URL可以带的内容)
     * @author: jiangbo <18883870892@163.com>
     * @date: 2017年12月11日 下午14:59:35
     * @throws
     */
    static public function urlsafe_b64encode($string) {
        $data = base64_encode($string);
        $data = str_replace(array('+','/','='),array('-','_',''),$data);
        return $data;
    }
    /**
     * @Title: urlsafe_b64decode
     * @Description: todo(解密码时把转换后的符号替换特殊符号)
     * @author: jiangbo <18883870892@163.com>
     * @date: 2017年12月11日 下午14:59:35
     * @throws
     */
    static public function urlsafe_b64decode($string) {
        $data = str_replace(array('-','_'),array('+','/'),$string);
        $mod4 = strlen($data) % 4;
        if ($mod4) {
            $data .= substr('====', $mod4);
        }
        return base64_decode($data);
    }
    /**
     * @Title: encryptByPri
     * @Description: todo(通过私钥加密数据)
     * @author: jiangbo <18883870892@163.com>
     * @date: 2017年12月11日 下午14:59:35
     * @throws
     */
    static public function encryptByPri($data,$private_key=''){
        // openssl genrsa -out rsa_private_key.pem 1024
        if(empty($private_key)) $private_key = RsaConf::PRIVATE_KEY;
        // 这个函数可用来判断私钥是否是可用的，可用返回资源id Resource id
        $pi_key = openssl_pkey_get_private($private_key);
        // rsa 是否可用
        if($pi_key === false) throw new \Exception("rsa is not available",1);
        // 私钥加密返回参数
        $encrypted = "";
        foreach (str_split($data, 117) as $chunk) {
            openssl_private_encrypt($chunk, $encryptData, $pi_key);
            $encrypted .= $encryptData;
        }
        // 加密后的内容通常含有特殊字符，需要编码转换下，在网络间通过url传输时要注意base64编码是否是url安全的
        return self::urlsafe_b64encode($encrypted);
    }
    /**
     * @Title: decryptByPri
     * @Description: todo(私钥解密)
     * @author: jiangbo <18883870892@163.com>
     * @date: 2017年12月11日 下午14:59:35
     * @throws
     */
    static public function decryptByPri($data,$private_key=''){
        // openssl genrsa -out rsa_private_key.pem 1024
        if(empty($private_key)) $private_key = RsaConf::PRIVATE_KEY;
        // 这个函数可用来判断私钥是否是可用的，可用返回资源id Resource id
        $pi_key = openssl_pkey_get_private($private_key);
        // rsa 是否可用
        if($pi_key === false) throw new \Exception("rsa is not available",1);
        // 私钥解密
        $decrypted = "";
        foreach (str_split(self::urlsafe_b64decode($data), 128) as $chunk) {
            openssl_private_decrypt($chunk, $decryptData, $pi_key);
            $decrypted .= $decryptData;
        }
        return $decrypted;
    }
    /**
     * @Title: encryptByPub
     * @Description: todo(公钥加密)
     * @author: jiangbo <18883870892@163.com>
     * @date: 2017年12月11日 下午14:59:35
     * @throws
     */
    static public function encryptByPub($data,$public_key=''){
        // openssl genrsa -out rsa_public_key.pem 1024
        if(empty($public_key)) $public_key = RsaConf::PUBLIC_KEY;
        // 这个函数可用来判断公钥是否是可用的，可用返回资源id Resource id
        $pu_key = openssl_pkey_get_public($public_key);
        // rsa 是否可用
        if($pu_key === false) throw new \Exception("rsa is not available",1);
        // 公钥加密返回参数
        $encrypted = "";
        foreach (str_split($data, 117) as $chunk) {
            openssl_public_encrypt($chunk, $encryptData, $pu_key);
            $encrypted .= $encryptData;
        }
        return self::urlsafe_b64encode($encrypted);
    }
    /**
     * @Title: decryptByPub
     * @Description: todo(通过公钥解密数据)
     * @author: jiangbo <18883870892@163.com>
     * @date: 2017年12月11日 下午14:59:35
     * @throws
     */
    static public function decryptByPub($data,$public_key=''){
        // openssl genrsa -out rsa_public_key.pem 1024
        if(empty($public_key)) $public_key = RsaConf::PUBLIC_KEY;
        // 这个函数可用来判断公钥是否是可用的，可用返回资源id Resource id
        $pu_key = openssl_pkey_get_public($public_key);
        // rsa 是否可用
        if($pu_key === false) throw new \Exception("rsa is not available",1);
        // 公钥解密
        $decrypted = "";
        foreach (str_split(self::urlsafe_b64decode($data), 128) as $chunk) {
            openssl_public_decrypt($chunk, $decryptData, $pu_key);
            $decrypted .= $decryptData;
        }
        return $decrypted;
    }
}